﻿using System;
using System.Linq.Expressions;

namespace movie.tool.library.binding
{
    public static class PropertyName
    {
        /// <summary>
        /// 通过访问属性的lambda表达式获取属性的名称。可以获取静态属性的名称，也可以获取实例对象属性的名称
        /// <para>Expression有不同的类型,枚举在<seealso cref="System.Linq.Expressions.ExpressionType"/>中</para>
        /// <para>在基类<seealso cref="System.Linq.Expressions.Expression"/>中,定义了此枚举属性NodeType</para>
        /// <para>由此每一个表达式都有它所属的类型，当获取此表达式后，就可以将其转换为对应类型的表达式类型</para>
        /// <para>访问属性的lambda表达式的Body属性是一个Expression,根据类型可以转换为MemberExpression,由此可以获取到属性的名称</para>
        /// <example>
        /// 举例: () => Class.Property 代表获取静态属性的名称，其中()代表此表达式没有参数;Class代表类名,如当前类就是PropertyName
        /// <para>Property代表静态属性</para>
        /// <para>() => object.Property代表获取实例对象的属性名称，其中()也是代表此表达式没有参数;object代表实例对象，Property代表实例对象的属性</para>
        /// </example>
        /// <para>其中,Func&lt;T&gt;代表一个委托，其没有参数，返回值类型为T</para>
        /// </summary>
        /// <typeparam name="T">属性的类型</typeparam>
        /// <param name="propertyLambda">访问属性的lambda表达式，格式为:() => Class.Property 或者 () => object.Property</param>
        /// <returns>属性的名称字符串</returns>
        public static string Get<T>(Expression<Func<T>> propertyLambda)
        {
            var me = propertyLambda.Body as MemberExpression;

            if (me == null)
            {
                throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
            }

            return me.Member.Name;
        }
    }
}
